/**
* @file    main.c
* @author  MenglongWu
* @version VEx1.2.3
* @date
* @brief   作者：吴梦龙\n
TS100——手持稳定光源，主程序接口
*

2013.03.15 吴梦龙
1、重新划分编译器rom空间，0x08000000 - 0x0803f7ff（0x3f800大小），
余下0x800（2K）空间用于存储校准信息，flash.h文件里开始写入开始地址是0x0803F800
********************************************************************************************************
*/


/* Includes ------------------------------------------------------------------*/
#include <autoconfig.h>
#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "prj_type.h"
#include "flash.h"

#include "misc.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "project.h"					//本工程的宏、函数、全局变量、结构体、版本信息、定义
#include "usart.h"						//串口
#include "minishell-tiny.h"
#include "do_shell.h"
#include "TR700Driver.h"
#include "stm32-chip-spi-tr700.h"
#include "env.h"



// struct fast_switch fastsw;				//快速校准功率、缩短AutoCtrlPower校准时间
// struct ctrl_param g_power;				/*< 功率设置 */

volatile u8 g_autoctrlpower_en = 1;






struct device_opm dev_opm;
unsigned long isdebug = 0;


/**
 * @brief	配置中断优先级
 * @param\n
 * @retval\n	NULL
 * @remarks	注：一共16个优先级，分为抢占式和响应式。两种优先级所占的数量由此代码确定，
NVIC_PriorityGroup_x可以是0、1、2、3、4，分别代表抢占优先级有1、2、4、8、16个和响应优先级有16、8、4、2、1个。
规定两种优先级的数量后，所有的中断级别必须在其中选择，抢占级别高的会打断其他中断优先执行，
而响应级别高的会在其他中断执行完优先执行。
 */
void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	/* Set the Vector Table base address at 0x08000000 */
	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);

	/* Configure the Priority Group to 2 bits */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	/* Enable the TIM5 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel					 = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority		 = 0;		 //响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the TIM5 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel					 = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	 //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority		 = 1;		 //响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the TIM5 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel					 = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the TIM5 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel					 = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel					 = TIM6_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority		 = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd				 = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}








struct cmd_prompt cmd_boot[] = {
#ifdef CONFIG_DO_LED
	PROMPT_NODE(NULL, do_led, "led", NULL, NULL),
#endif
#ifdef CONFIG_DO_DAC
	PROMPT_NODE(NULL, do_dac, "dac", NULL, NULL),
#endif
#ifdef CONFIG_DO_LASER
	PROMPT_NODE(NULL, do_laser, "laser", NULL, NULL),
#endif
#ifdef CONFIG_DO_OPM
	PROMPT_NODE(NULL, do_opm, "opm", NULL, NULL),
#endif
	PROMPT_NODE(NULL, do_show, "show", NULL, NULL),
	PROMPT_NODE(NULL, do_watch, "watch", NULL, NULL),
	PROMPT_NODE(NULL, do_adj, "adj", NULL, NULL),
	PROMPT_NODE(NULL, do_setenv, "setenv", NULL, NULL),
	PROMPT_NODE(NULL, do_save, "save", NULL, NULL),
	PROMPT_NODE(NULL, NULL, NULL, NULL, NULL),
};
#include "stm32f10x_spi.h"
extern char spi_dates[100];
extern int spi_index;
extern unsigned int spi_jiffies;
extern unsigned int spi_count;
extern int arr_index[10];
extern int arr_isr[10];
extern int arr_cr2[10];
extern unsigned int spi_newlen;
#define TASK_DETA_USART   (100 * _1MS)
#define TASK_DETA_SPI_SHOW  (10 * _1MS)
#define TASK_DETA_AUTO_LS  (100 * _1MS)
#define TASK_DETA_AUTO_OPM  (100 * _1MS)



// 环境变量转换成具体数据类型并提供高速访问，避免每次都要访问环境变量字符串
struct system_param sys_param;

int maxlen = 32;

// 存储于FLASH的环境变量
struct load_env sys_vals[] = {
	{"sn", 		&sys_param.sn, 		&maxlen,   envtostr, ENV_T_STR},
	{"ch1_10_adc", 	&sys_param.ch1_10_adc, 	NULL, envtos, ENV_T_SHORT},
	{"ch1_10_dac", 	&sys_param.ch1_10_dac, 	NULL, envtos, ENV_T_SHORT},
	{"ch2_10_adc", 	&sys_param.ch2_10_adc, 	NULL, envtos, ENV_T_SHORT},
	{"ch2_10_dac", 	&sys_param.ch2_10_dac, 	NULL, envtos, ENV_T_SHORT},
	{"ch3_10_adc", 	&sys_param.ch3_10_adc, 	NULL, envtos, ENV_T_SHORT},
	{"ch3_10_dac", 	&sys_param.ch3_10_dac, 	NULL, envtos, ENV_T_SHORT},

	{"ch1_wave", 	&sys_param.ch1_wave, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},
	{"ch2_wave", 	&sys_param.ch2_wave, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},
	{"ch3_wave", 	&sys_param.ch3_wave, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},
	{"ch1_en", 	&sys_param.ch1_en, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},
	{"ch2_en", 	&sys_param.ch2_en, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},
	{"ch3_en", 	&sys_param.ch3_en, 	NULL, envtos, ENV_T_SHORT},//TODO 修改成 envtoi, ENV_T_INT},

	{"lv1_low", 	&sys_param.lv1_low,	NULL, envtos, ENV_T_SHORT},
	{"lv1_high", 	&sys_param.lv1_high,	NULL, envtos, ENV_T_SHORT},
	{"lv2_low", 	&sys_param.lv2_low,	NULL, envtos, ENV_T_SHORT},
	{"lv2_high", 	&sys_param.lv2_high,	NULL, envtos, ENV_T_SHORT},
	{"lv3_low", 	&sys_param.lv3_low,	NULL, envtos, ENV_T_SHORT},
	{"lv3_high", 	&sys_param.lv3_high,	NULL, envtos, ENV_T_SHORT},
	{"lv4_low", 	&sys_param.lv4_low,	NULL, envtos, ENV_T_SHORT},
	{"lv4_high", 	&sys_param.lv4_high,	NULL, envtos, ENV_T_SHORT},
	{"lv5_low", 	&sys_param.lv5_low,	NULL, envtos, ENV_T_SHORT},
	{"lv5_high", 	&sys_param.lv5_high,	NULL, envtos, ENV_T_SHORT},
	{"lv6_low", 	&sys_param.lv6_low,	NULL, envtos, ENV_T_SHORT},
	{"lv6_high", 	&sys_param.lv6_high,	NULL, envtos, ENV_T_SHORT},
	{"lv7_low", 	&sys_param.lv7_low,	NULL, envtos, ENV_T_SHORT},
	{"lv7_high", 	&sys_param.lv7_high,	NULL, envtos, ENV_T_SHORT},

	{"_1550_ref_1310", &sys_param._1550_ref_1310, 	NULL, envtof, ENV_T_FLOAT},
	{"_1490_ref_1310", &sys_param._1490_ref_1310, 	NULL, envtof, ENV_T_FLOAT},
	{"_1625_ref_1310", &sys_param._1625_ref_1310, 	NULL, envtof, ENV_T_FLOAT},
	{"_850_ref_1310",  &sys_param._850_ref_1310, 	NULL, envtof, ENV_T_FLOAT},
};



int main(void)
{
	int lic[4];
	struct device_ls v;
	unsigned long after, after2;
	unsigned long task_spi, task_usart, task_ls, task_opm;
	unsigned short date;
	char uch = 0;
	int tindex = 0;
	int i;

	struct tr700_getopm       getopm;
	struct tr700_getopm_dbg   getopm_dbg;
	struct tr700_getls_dbg    getls_dbg;

	unsigned short           adc     = 0;
	float                    dbm     = 0;
	int                      lv      = 0;

	// TODO 下面的若干初始化工作需要结构化，虽然能工作，但阅读不易
	// 修改成linux下的类似 platform_device
	dev_ls.ch    = CTRL_CH1;
	dev_ls.mode  = LASER_MODE_CW;
	dev_ls.o_dbm = -10.00;

	USART_Configuration();
	printf("\n\n----------------------------------------------------------\r\n");
	printf("        GLink TR700-LS-OPM Runing\r\n");
	FLASH_Configuration();
	env_2_system(sys_vals, ARRAY_SIZE(sys_vals));
	_do_setenv("wml", "abc");
	{
		// TODO adj_power_flash 改成 struct overflow_limit_data
		struct adj_power_flash adj;

		adj.lv1_low  = sys_param.lv1_low;
		adj.lv1_high = sys_param.lv1_high;
		adj.lv2_low  = sys_param.lv2_low;
		adj.lv2_high = sys_param.lv2_high;
		adj.lv3_low  = sys_param.lv3_low;
		adj.lv3_high = sys_param.lv3_high;
		adj.lv4_low  = sys_param.lv4_low;
		adj.lv4_high = sys_param.lv4_high;
		adj.lv5_low  = sys_param.lv5_low;
		adj.lv5_high = sys_param.lv5_high;
		adj.lv6_low  = sys_param.lv6_low;
		adj.lv6_high = sys_param.lv6_high;
		adj.lv7_low  = sys_param.lv7_low;
		adj.lv7_high = sys_param.lv7_high;

		Init_Overflow(&adj);
	}
	do_printenv();
	Init_LED();
	Init_Laser();
	Ctrl_LaserChannel(&dev_ls);
	Init_LaserPower();
	v.dac = 3080;
	Ctrl_LaserPower(&v);
	ADC_Configuration();
	Init_OPM_SW();
	Ctrl_OPM_SW(3);
	Ctrl_OPMWave(CTRL_OPM_WAVE_1310);
	SPI_Slave();
	EXTI_SPI();

	TIM6_Init();
	NVIC_Configuration();


	sh_whereboot(cmd_boot);

	task_usart = jiffies + TASK_DETA_USART;
	task_spi   = jiffies + TASK_DETA_SPI_SHOW;
	task_ls    = jiffies + 34 * _1MS;  // 错开启动时间
	task_opm   = jiffies + 14 * _1MS;

	fill_getls_dbg(&getls_dbg);
	fill_getopm_dbg(&getopm_dbg);
	fill_getopm(&getopm);
	while(1) {
		if (time_before(jiffies, task_usart)) {
			PeekUartCmd();
		} else {
			task_usart = jiffies + TASK_DETA_USART;
		}


		if (spi_active_cmd) {
			on_active();
		}
#if 0
		if (time_after(jiffies, task_spi)) {
			task_spi = jiffies + TASK_DETA_SPI_SHOW;
			if (spi_index) {
				printf("\r\n spi [%d] %d [%d]\r\n", spi_index, spi_count, spi_newlen);
				for (i = 0; i < spi_count; i++) {
					printf("%d isr %x	cr2	%x\r\n", arr_index[i], arr_isr[i], arr_cr2[i]);
				}
				printf("\r\n");
				for (i = 0; i < spi_index; i++) {
					printf("%2.2x ", spi_dates[i]);
				}
				spi_index = 0;
			}
		}
#endif
		if (time_after(jiffies, task_ls)) {
			task_ls = jiffies + TASK_DETA_AUTO_LS;
			if (!SPI_ISDEBUG()) {
				AutoCtrl_LS();
			} else {
				getls_dbg.ch   = dev_ls.ch;
				getls_dbg.mode = dev_ls.mode;
				getls_dbg.adc  = GetAD(AD_CH_LS);
				getls_dbg.dac  = dev_ls.dac;
				fill_getls_dbg(&getls_dbg);
			}
		}
		if (time_after(jiffies, task_opm)) {
			task_opm = jiffies + TASK_DETA_AUTO_OPM;
			if (!SPI_ISDEBUG()) {
				AutoCtrl_OPM();
			} else {
				getopm_dbg.level = lv;
				getopm_dbg.adc   = adc;
				getopm_dbg.dbm   = getopm.dbm;

				fill_getopm_dbg(&getopm_dbg);
			}
			adc = GetAD(AD_CH_OPM);
			getopm.dbm = AutoADC2dBm();
			lv  = Get_OPM_SW();
			fill_getopm(&getopm);

		}
	}
}


